﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using log4net;
using com.IronOne.BoardAppWeb.Controllers;
using System.Net.Mail;
using System.Configuration;
using System.Net;
using System.Web.UI.WebControls;
using System.Collections.Specialized;
using System.Text;
using System.IO;


namespace com.IronOne.BoardAppWeb.Models.General
{
    public class EmailHandler
    {
        // protected static readonly ILog log = LogManager.GetLogger("root");
        protected static ILog EventLog = LogManager.GetLogger("EventLog");
        protected static ILog ErrorLog = LogManager.GetLogger("ErrorLog");

        //  public System.Net.Mail.MailMessage mailMsg { get; set; }
        MailDefinition mailDef;
        string mailTo = string.Empty;

        #region Constructors

        public EmailHandler()
        {

        }

        // for sending single email
        public EmailHandler(string subject, string from, string to, string templatePath)
        {
            try
            {
                #region Validations
                if (String.IsNullOrWhiteSpace(from))
                {
                    throw new GenException("err_584_sys");
                }
                if (String.IsNullOrWhiteSpace(to))
                {
                    throw new GenException("err_585_sys");
                }
                if (String.IsNullOrWhiteSpace(templatePath))
                {
                    throw new GenException("err_586_sys");
                }
                #endregion Validations

                mailDef = new MailDefinition();
                mailDef.Subject = subject;
                mailDef.BodyFileName = templatePath;
                mailDef.From = from;
                mailTo = to;
            }
            catch (ArgumentNullException)
            {
                throw;
            }
            catch (Exception)
            {
                throw;
            }
        }

        // for sending multiple emails
        public EmailHandler(string subject, string from, string templatePath)
        {
            try
            {
                #region Validations
                if (String.IsNullOrWhiteSpace(from))
                {
                    throw new GenException("err_584_sys");
                }
                if (String.IsNullOrWhiteSpace(templatePath))
                {
                    throw new GenException("err_586_sys");
                }
                #endregion Validations

                mailDef = new MailDefinition();
                mailDef.Subject = subject;
                mailDef.BodyFileName = templatePath;
                mailDef.From = from;
            }
            catch (ArgumentNullException)
            {
                throw;
            }
            catch (Exception)
            {
                throw;
            }
        }

        #endregion Constructors

        #region PublicMethods

        public System.Net.Mail.MailMessage CreateMailMessage(ListDictionary replacements)
        {
            // Initialize EmailHandler(string subject, string from, string to, string templatePath) Constructor Befpre Calling this method
            try
            {
                #region Validations
                if (mailDef == null)
                {
                    throw new GenException("err_587_sys");
                }
                if (String.IsNullOrWhiteSpace(mailTo))
                {
                    throw new GenException("err_585_sys");
                }
                if (replacements == null)
                {
                    throw new GenException("err_588_sys");
                }
                #endregion Validations

                return mailDef.CreateMailMessage(mailTo, replacements, new System.Web.UI.Control());
            }
            catch (GenException)
            {
                throw;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public System.Net.Mail.MailMessage CreateMailMessage(string to, ListDictionary replacements)
        {
            // Initialize  EmailHandler(string subject, string from,  string templatePath) Constructor Befpre Calling this method
            try
            {
                #region Validations
                if (mailDef == null)
                {
                    throw new GenException("err_587_sys");
                }
                if (replacements == null)
                {
                    throw new GenException("err_588_sys");
                }
                #endregion Validations

                return mailDef.CreateMailMessage(to, replacements, new System.Web.UI.Control());
            }
            catch (GenException)
            {
                throw;
            }
            catch (Exception)
            {
                throw;
            }
        }

        #endregion PublicMethods

        #region PrivateMethods

        private SmtpClient CreateSMTPClient()
        {
            try
            {
                bool sslOn = Convert.ToBoolean(ConfigurationManager.AppSettings["SSL_Enable"]);
                SmtpClient client = /*BoardAppUtil.Settings.Settings.GetEmailConfigs(sslOn);*/ new SmtpClient();
                client.Timeout = 300000;//default is  100,000 - 100 seconds
                try
                {
                    //Set from web config
                    client.Timeout = int.Parse(ConfigurationManager.AppSettings["SMTP_Cleint_Timeout"].ToString());
                }
                catch (Exception)
                {
                    //  do nothing
                }
                //client.Host = ConfigurationManager.AppSettings["EmailClient"].ToString(); //Set your smtp host address
                //client.Port = int.Parse(ConfigurationManager.AppSettings["EmailPort"].ToString()); // Set your smtp port address
                client.DeliveryMethod = SmtpDeliveryMethod.Network;
                //client.Credentials = new NetworkCredential(ConfigurationManager.AppSettings["EmailUserName"].ToString(), ConfigurationManager.AppSettings["EmailPassword"].ToString()); //account name and password
                //bool sslOn = Convert.ToBoolean(ConfigurationManager.AppSettings["SSL_Enable"]);
                //if (sslOn)
                //{
                   // client.EnableSsl = true;    // Set SSL = true   
                //}
                return client;
            }
            catch (Exception)
            {
                throw new GenException("err_583_sys");
            }
        }

        private AlternateView AddAlternativeView(Meeting.MeetingModel meeting, MailMessage msg, EmailAlternativeView emailAlternativeView)
        {
            try
            {
                System.Net.Mime.ContentType ct = null;
                string content = "";

                switch (emailAlternativeView)
                {
                    case EmailAlternativeView.Html:
                        ct = new System.Net.Mime.ContentType("text/html");
                        content = Generate_HTMLString(meeting, msg);
                        break;
                    case EmailAlternativeView.Calender:
                        ct = new System.Net.Mime.ContentType("text/calendar");
                        content = Generate_ICSString(meeting, msg);
                        break;
                    case EmailAlternativeView.Text:
                        ct = new System.Net.Mime.ContentType("text/calendar");
                        content = Generate_TextString(meeting, msg);
                        break;
                    default: return null;
                }

                ct.Parameters.Add("method", "REQUEST");

                AlternateView av = AlternateView.CreateAlternateViewFromString(content, ct);
                return av;
            }
            catch (GenException)
            {
                throw;
            }
            catch (Exception)
            {
                throw;
            }
        }

        private string Generate_ICSString(Meeting.MeetingModel meeting, MailMessage msg)
        {
            try
            {
                DateTime? startDate = meeting.StartDateWithTime;
                DateTime? endDate = meeting.EndDateWithTime;             
                
                StringBuilder str = new StringBuilder();
                str.AppendLine("BEGIN:VCALENDAR");
                str.AppendLine("PRODID:-// Ironone Board App");
                str.AppendLine("VERSION:2.0");
                str.AppendLine("METHOD:REQUEST");
                str.AppendLine("BEGIN:VEVENT");
                str.AppendLine(string.Format("DTSTART:{0:yyyyMMddTHHmmss}", startDate)); //str.AppendLine(string.Format("DTSTART:{0:yyyyMMddTHHmmssZ}", startDate));//UTC Time
                str.AppendLine(string.Format("DTSTAMP:{0:yyyyMMddTHHmmss}", DateTime.Now));
                str.AppendLine(string.Format("DTEND:{0:yyyyMMddTHHmmss}", endDate));//SET END DATE!!!
                str.AppendLine(string.Format("LOCATION: {0}", "Board room"));// SET LOCATION HERE!!!
                str.AppendLine(string.Format("UID:{0}", Guid.NewGuid()));
                str.AppendLine(string.Format("DESCRIPTION:{0}", msg.Body));
                str.AppendLine(string.Format("X-ALT-DESC;FMTTYPE=text/html:{0}", msg.Body));
                str.AppendLine(string.Format("SUMMARY:{0}", msg.Subject));
                str.AppendLine(string.Format("ORGANIZER:MAILTO:{0}", msg.From.Address));
                str.AppendLine(string.Format("ATTENDEE;CN=\"{0}\";RSVP=TRUE:mailto:{1}", msg.To[0].DisplayName, msg.To[0].Address));
                str.AppendLine("BEGIN:VALARM");
                str.AppendLine("TRIGGER:-PT15M");
                str.AppendLine("ACTION:DISPLAY");
                str.AppendLine("DESCRIPTION:Reminder");
                str.AppendLine("END:VALARM");
                str.AppendLine("END:VEVENT");
                str.AppendLine("END:VCALENDAR");
                return str.ToString();
            }
            catch (GenException)
            {
                throw;
            }
            catch (Exception)
            {
                throw new GenException("err_580_sys");
            }
        }

        private string Generate_HTMLString(Meeting.MeetingModel meeting, MailMessage msg)
        {
            try
            {
                throw new NotImplementedException();
            }
            catch (Exception)
            {
                throw new GenException("err_581_sys");
            }
        }

        private string Generate_TextString(Meeting.MeetingModel meeting, MailMessage msg)
        {
            try
            {
                throw new NotImplementedException();
            }
            catch (Exception)
            {
                throw new GenException("err_582_sys");
            }
        }

        #endregion PrivateMethods

        #region ThreadMethods

        public void SendMail(System.Net.Mail.MailMessage mailMsg)
        {
            try
            {
                EventLog.Info("0, " + "EVT, " + EventStatus.Entry.ToString() + ", Email Handler" + ", Send Mail, Thread action, [Parameters=(Meeting Id: " + mailMsg.Subject + ")]");

                if (mailMsg == null)
                    throw new GenException("err_552_sys");

                SmtpClient client = this.CreateSMTPClient();
                client.Send(mailMsg);

                EventLog.Info("0, " + "EVT, " + EventStatus.Success.ToString() + ", Email Handler" + ", Send Mail, Thread action, [Email has been sent to :" + mailMsg.To + ", Subject:" + mailMsg.Subject + ", from:" + mailMsg.From + "]");

                mailMsg.Dispose();
                client.Dispose();
            }
            catch (GenException ex)
            {
                EventLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ",Send Mail, Thread action,, " + com.IronOne.BoardAppWeb.Lang.Resources.err_550);
                ErrorLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Mail, Thread action,," + ex.Message);
            }
            catch (SmtpException ex)
            {
                EventLog.Info("551, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ",Send Mail, Thread action,, " + com.IronOne.BoardAppWeb.Lang.Resources.err_551);
                ErrorLog.Info("551, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Mail, Thread action,," + ex.Message + "[Email has NOT been sent to :" + mailMsg.To + ", Subject:" + mailMsg.Subject + ", from:" + mailMsg.From + "]");
            }
            catch (Exception ex)
            {
                EventLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Mail, Thread action, " + com.IronOne.BoardAppWeb.Lang.Resources.err_550);
                ErrorLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Mail, Thread action," + ex.Message + "[Email has NOT been sent to :" + mailMsg.To + ", Subject:" + mailMsg.Subject + ", from:" + mailMsg.From + "]");
            }
        }

        public void SendMail(List<System.Net.Mail.MailMessage> mailMsgs)
        {
            try
            {
                EventLog.Info("0, " + "EVT, " + EventStatus.Entry.ToString() + ", Email Handler" + ", Send Multiple Mails , Thread action");//+ HttpContext.Current.User.Identity.Name);

                if (mailMsgs == null || mailMsgs.Count == 0)
                    throw new GenException("err_553_sys");

                SmtpClient client = this.CreateSMTPClient();

                foreach (System.Net.Mail.MailMessage mail in mailMsgs)
                {
                    try
                    {
                        client.Send(mail);
                        EventLog.Info("0, " + "EVT, " + EventStatus.Success.ToString() + ", Email Handler" + ", Send Multiple Mails, Thread action, [Email has been sent to :" + mail.To + ", Subject:" + mail.Subject + ", from:" + mail.From + "]");
                    }
                    catch (SmtpException ex)
                    {
                        //EventLog.Info("922, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ",Send Multiple Mails, Thread action,, " + com.IronOne.BoardAppWeb.Lang.Resources.err_922);
                        ErrorLog.Info("551, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Multiple Mails, Thread action,," + ex.Message + "[Email has NOT been sent to :" + mail.To + ", Subject:" + mail.Subject + ", from:" + mail.From + "]");
                    }
                    catch (Exception ex)
                    {
                        //EventLog.Info("221, " + "ERR, " + EventStatus.Failure.ToString() + ", Meeting" + ", Send Multiple Mails,Thread action, " + com.IronOne.BoardAppWeb.Lang.Resources.err_221);
                        ErrorLog.Info("err_550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Multiple Mails, Thread action," + ex.Message + "[Email has NOT been sent to :" + mail.To + ", Subject:" + mail.Subject + ", from:" + mail.From + "]");
                    }
                }
                client.Dispose();
                EventLog.Info("0, " + "EVT, " + EventStatus.Success.ToString() + ", Email Handler" + ", Send Multiple Mails, Thread action, [All emails have been sent. Recipients count:" + mailMsgs.Count + "]");
            }
            catch (GenException ex)
            {
                EventLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Multiple Mails, Thread action, " + com.IronOne.BoardAppWeb.Lang.Resources.err_550);
                ErrorLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Multiple Mails, Thread action," + ex.Message);
            }
            catch (SmtpException ex)
            {
                EventLog.Info("551, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ",Send  Multiple Mails, Thread action,, " + com.IronOne.BoardAppWeb.Lang.Resources.err_551);
                ErrorLog.Info("551, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Multiple Mails, Thread action,," + ex.Message);
            }
            catch (Exception ex)
            {
                EventLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Multiple Mails, Thread action, " + com.IronOne.BoardAppWeb.Lang.Resources.err_550);
                ErrorLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Multiple Mails, Thread action," + ex.Message);
            }
        }

        //single meeting request
        public void SendMeetingRequest(Meeting.MeetingModel meeting, MailMessage msg)
        {
            try
            {
                EventLog.Info("0, " + "EVT, " + EventStatus.Entry.ToString() + ", Email Handler" + ", Send Meeting Request , Thread action");//+ HttpContext.Current.User.Identity.Name);

                SmtpClient sc = this.CreateSMTPClient();

                //Get Calender alternative View
                AlternateView avCal = AddAlternativeView(meeting, msg, EmailAlternativeView.Calender);
                msg.AlternateViews.Add(avCal);

                //Send mail
                sc.Send(msg);

                EventLog.Info("0, " + "EVT, " + EventStatus.Success.ToString() + ", Email Handler" + ", Send Meeting Request, Thread action, [Meeting requests have been sent. Subject:" + msg.Subject + "]");
                msg.Dispose();
                sc.Dispose();
            }
            catch (GenException ex)
            {
                EventLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Meeting Request, Thread action, " + com.IronOne.BoardAppWeb.Lang.Resources.err_550);
                ErrorLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Meeting Request, Thread action," + ex.Message);
            }
            catch (SmtpException ex)
            {
                EventLog.Info("551, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ",Send Meeting Request, Thread action,, " + com.IronOne.BoardAppWeb.Lang.Resources.err_551);
                ErrorLog.Info("551, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Meeting Request, Thread action,," + ex.Message);
            }
            catch (Exception ex)
            {
                EventLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Meeting Request, Thread action, " + com.IronOne.BoardAppWeb.Lang.Resources.err_550);
                ErrorLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Meeting Request, Thread action," + ex.Message);
            }
        }

        //Multiple meeting requests for the same meeting
        public void SendMeetingRequest(Meeting.MeetingModel meeting, List<System.Net.Mail.MailMessage> msgs)
        {
            try
            {
                EventLog.Info("0, " + "EVT, " + EventStatus.Entry.ToString() + ", Email Handler" + ", Send Meeting Request , Thread action");//+ HttpContext.Current.User.Identity.Name);

                SmtpClient sc = this.CreateSMTPClient();

                foreach (System.Net.Mail.MailMessage mail in msgs)
                {
                    try
                    {
                        //Get Calender alternative View
                        AlternateView avCal = AddAlternativeView(meeting, mail, EmailAlternativeView.Calender);
                        mail.AlternateViews.Add(avCal);

                        //Send mail
                        sc.Send(mail);
                        EventLog.Info("0, " + "EVT, " + EventStatus.Success.ToString() + ", Email Handler" + ", Send Multiple Mails, Thread action, [Email has been sent to :" + mail.To + ", Subject:" + mail.Subject + ", from:" + mail.From + "]");
                    }
                    catch (SmtpException ex)
                    {
                        //EventLog.Info("922, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ",Send Multiple Mails, Thread action,, " + com.IronOne.BoardAppWeb.Lang.Resources.err_922);
                        ErrorLog.Info("551, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Meeting Request, Thread action,," + ex.Message + "[Email has NOT been sent to :" + mail.To + ", Subject:" + mail.Subject + ", from:" + mail.From + "]");
                    }
                    catch (Exception ex)
                    {
                        //EventLog.Info("221, " + "ERR, " + EventStatus.Failure.ToString() + ", Meeting" + ", Send Multiple Mails,Thread action, " + com.IronOne.BoardAppWeb.Lang.Resources.err_221);
                        ErrorLog.Info("err_550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Meeting Request, Thread action," + ex.Message + "[Email has NOT been sent to :" + mail.To + ", Subject:" + mail.Subject + ", from:" + mail.From + "]");
                    }
                }
                EventLog.Info("0, " + "EVT, " + EventStatus.Success.ToString() + ", Email Handler" + ", Send Meeting Request, Thread action, [Meeting requests have been sent. Total emails count:" + msgs.Count + "]");

                sc.Dispose();
            }
            catch (GenException ex)
            {
                EventLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Meeting Request, Thread action, " + com.IronOne.BoardAppWeb.Lang.Resources.err_550);
                ErrorLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Meeting Request, Thread action," + ex.Message);
            }
            catch (SmtpException ex)
            {
                EventLog.Info("551, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ",Send Meeting Request, Thread action,, " + com.IronOne.BoardAppWeb.Lang.Resources.err_551);
                ErrorLog.Info("551, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Meeting Request, Thread action,," + ex.Message);
            }
            catch (Exception ex)
            {
                EventLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Meeting Request, Thread action, " + com.IronOne.BoardAppWeb.Lang.Resources.err_550);
                ErrorLog.Info("550, " + "ERR, " + EventStatus.Failure.ToString() + ", Email Handler" + ", Send Meeting Request, Thread action," + ex.Message);
            }
        }

        #endregion ThreadMethods

        #region TestMethods

        //WORKING!!! 
        public void SendMeetingRequest()
        {
            DateTime startTime = DateTime.Now;
            DateTime endTime = DateTime.Now.AddDays(2);
            string location = "Colombo";

            SmtpClient sc = this.CreateSMTPClient();
            MailMessage msg = new MailMessage();

            msg.From = new MailAddress("lushanthanucsc@gmail.com", "Lushanthan ucsc");
            msg.To.Add(new MailAddress("lushanthans@irononetech.com", "Lush Fe1"));

            msg.Subject = "Send Calendar Appointment Email 11";
            msg.Body = ""; // Add Body Message Here

            StringBuilder str = new StringBuilder();
            str.AppendLine("BEGIN:VCALENDAR");
            str.AppendLine("PRODID:-// Ironone Board App");
            str.AppendLine("VERSION:2.0");
            str.AppendLine("METHOD:REQUEST");
            str.AppendLine("BEGIN:VEVENT");
            str.AppendLine(string.Format("DTSTART:{0:yyyyMMddTHHmmssZ}", startTime));
            str.AppendLine(string.Format("DTSTAMP:{0:yyyyMMddTHHmmssZ}", DateTime.UtcNow));
            str.AppendLine(string.Format("DTEND:{0:yyyyMMddTHHmmssZ}", endTime));
            str.AppendLine(string.Format("LOCATION: {0}", location));
            str.AppendLine(string.Format("UID:{0}", Guid.NewGuid()));
            str.AppendLine(string.Format("DESCRIPTION:{0}", msg.Body));
            str.AppendLine(string.Format("X-ALT-DESC;FMTTYPE=text/html:{0}", msg.Body));
            str.AppendLine(string.Format("SUMMARY:{0}", msg.Subject));
            str.AppendLine(string.Format("ORGANIZER:MAILTO:{0}", msg.From.Address));
            str.AppendLine(string.Format("ATTENDEE;CN=\"{0}\";RSVP=TRUE:mailto:{1}", msg.To[0].DisplayName, msg.To[0].Address));
            str.AppendLine("BEGIN:VALARM");
            str.AppendLine("TRIGGER:-PT15M");
            str.AppendLine("ACTION:DISPLAY");
            str.AppendLine("DESCRIPTION:Reminder");
            str.AppendLine("END:VALARM");
            str.AppendLine("END:VEVENT");
            str.AppendLine("END:VCALENDAR");

            System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType("text/calendar");
            ct.Parameters.Add("method", "REQUEST");

            AlternateView avCal = AlternateView.CreateAlternateViewFromString(str.ToString(), ct);
            msg.AlternateViews.Add(avCal);

            sc.Send(msg);
            msg.Dispose();
            sc.Dispose();
        }

        #endregion TestMethods
    }

    public enum EmailAlternativeView
    {
        Html = 1,
        Calender,
        Text
    }
}